package util

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"go.mongodb.org/mongo-driver/bson/bsontype"
	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
	"gopkg.in/mgo.v2/bson"
)

const (
	ctLayout    = "2006-01-02 15:04:05"
	CtLayoutDay = "2006-01-02"
)

type CustomTime struct {
	time.Time
}

func Time(str string) time.Time {
	location, _ := time.LoadLocation("Asia/Shanghai")
	tm, _ := time.ParseInLocation(ctLayout, str, location)
	return tm
}

func TimeStr(t time.Time) string {
	return t.Local().Format(ctLayout)
}

func IntToTime(t int64) time.Time {
	return time.Unix(t, 0)
}

func TimeDay(str string) time.Time {
	location, _ := time.LoadLocation("Asia/Shanghai")
	tm, _ := time.ParseInLocation(CtLayoutDay, str, location)
	return tm
}

func TimeDayStr(t time.Time) string {
	return t.Local().Format(CtLayoutDay)
}

func TimeDayStart(currDate string) time.Time {
	return Time(fmt.Sprintf("%s 00:00:00", currDate))
}

func TimeDayEnd(currDate string) time.Time {
	return Time(fmt.Sprintf("%s 23:59:59", currDate))
}

func NewCustomTime(str string) *CustomTime {
	location, _ := time.LoadLocation("Asia/Shanghai")
	tm, _ := time.ParseInLocation(ctLayout, str, location)
	return &CustomTime{tm}
}

func (t *CustomTime) MarshalJSON() ([]byte, error) {
	if t.IsZero() {
		return json.Marshal("-")
	}
	return []byte(fmt.Sprintf(`"%s"`, t.Format(ctLayout))), nil
}

func (t *CustomTime) UnmarshalJSON(data []byte) error {
	str := string(data)
	str = strings.Trim(str, "\"")
	location, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		return err
	}
	tm, err := time.ParseInLocation(ctLayout, str, location)
	if err != nil {
		return err
	}
	t.Time = tm
	return nil
}

func (t *CustomTime) Scan(src interface{}) error {
	if src == nil {
		*t = CustomTime{time.Time{}}
	}
	*t = CustomTime{src.(time.Time)}
	return nil
}

func (t *CustomTime) Value() (driver.Value, error) {
	if t.Time.IsZero() {
		return nil, nil
	}
	return t.Time, nil
}

//mongo-driver bson
func (t *CustomTime) MarshalBSON() ([]byte, error) {
	return bson.Marshal(t.Time)
}

func (t *CustomTime) UnmarshalBSON(data []byte) error {
	return bson.Unmarshal(data, &t.Time)
}

func (t *CustomTime) MarshalBSONValue() (bsontype.Type, []byte, error) {
	return bsontype.DateTime, bsoncore.AppendTime(nil, t.Time), nil
}

func (t *CustomTime) UnmarshalBSONValue(typ bsontype.Type, data []byte) error {
	time, _, _ := bsoncore.ReadTime(data)
	t.Time = time
	return nil
}

//获取某一天的0点时间
func GetZeroTime(d time.Time) time.Time {
	return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
}
